

#include  "ESS_CommonDefine.h"
#include  "PackInfor\PackInformationReading.h"
#include  "Drivers\Drivers.h"
#include "Communication\SMBUS_Define.h"
#include "SystemConfigDefineByFlash.h"

extern const unsigned char PackCommand[]; 
unsigned char CheckingPackVoltageForMosFETConnectingInto( char packNum );
void CheckingPackMosFETStatus( char packNum );


unsigned int getDeltaVoltageWithMosFETOn(char moduleName, char packNum){

  unsigned char packs_loop;
  unsigned char count;
  unsigned int packValue, tempValue;
  unsigned long sumValue;
  
  count = 0;
  sumValue = 0;

  for(packs_loop = _A; packs_loop <= _F; packs_loop++){
    if(packs_loop == packNum){
      packValue = module[moduleName].pack[packNum].packInfo[voltage][0];
      packValue |= module[moduleName].pack[packNum].packInfo[voltage][1] << 8;
      continue;
    }
    if( module[moduleName].pack[packs_loop].packFail == PackNormal && 
        module[moduleName].pack[packs_loop].packInfoFail[voltage] == PackNormal &&
        isPackFETTurnOn_ByManufacturerAccess(moduleName, packs_loop)  )
    {
      tempValue = module[moduleName].pack[packs_loop].packInfo[voltage][0];
      tempValue |= module[moduleName].pack[packs_loop].packInfo[voltage][1] << 8;
      sumValue += tempValue;
      count++;
    }
  }//for(packs_loop = _A; packs_loop <= _F; packs_loop++){
  sumValue = sumValue/count;
  tempValue = (unsigned int)sumValue;
  if(tempValue >= packValue){
    return (tempValue - packValue);
  }else{
    return (packValue - tempValue);
  }
}

void PackMosFETControlAtChangingNewOne( char packNum, unsigned char Out_moduleOfPackChangedNewOneBit ){
  
  unsigned int DeltaValue;
  unsigned char flag, status;
  
  char gettingStatus;
  unsigned char cmd;
  unsigned char readWordData[Pack_Data_Buffer_SIZE];
   
  status = Out_moduleOfPackChangedNewOneBit;
  flag = 0;
  DeltaValue = 0;
  //////////////////////////////////
  //turn off pack mos fet
  // and update voltage and ManufacturerAccess
  if(status != 0){
    if(status & BIT0){
      //module1 pack
        flag = setPackMosFET(_M1, DeviceOff);
        if(flag){
          flag = setPackMosFET(_M1, DeviceOff);
        }
      if(flag){
        Init_USCI_B0_IIC();
        module[_M1].pack[packNum].packFail = PackCommunctionFail;
        DeltaValue++;
      }else{
        // update voltage and ManufacturerAccess
        module[_M1].pack[packNum].packInfo[ManufacturerAccess][0] = 0x00;
        module[_M1].pack[packNum].packInfo[ManufacturerAccess][1] = 0x00;
        cmd = PackCommand[voltage];
        readWordData[0] = 0;
        readWordData[1] = 0;
        gettingStatus = getPackInformation(_M1, cmd, readWordData);
        if(gettingStatus == None){
          module[_M1].pack[packNum].packInfo[voltage][0] = readWordData[0];
          module[_M1].pack[packNum].packInfo[voltage][1] = readWordData[1];
        }
      }
    }//if(status & BIT0){
    if(status & BIT1){
      //module2 pack
        flag = setPackMosFET(_M2, DeviceOff);
        if(flag){
          flag = setPackMosFET(_M2, DeviceOff);
        }
      if(flag){
        Init_USCI_B1_IIC();
        module[_M2].pack[packNum].packFail = PackCommunctionFail;
        DeltaValue++;
      }else{
        // update voltage and ManufacturerAccess
        module[_M2].pack[packNum].packInfo[ManufacturerAccess][0] = 0x00;
        module[_M2].pack[packNum].packInfo[ManufacturerAccess][1] = 0x00;
        cmd = PackCommand[voltage];
        readWordData[0] = 0;
        readWordData[1] = 0;
        gettingStatus = getPackInformation(_M2, cmd, readWordData);
        if(gettingStatus == None){
          module[_M2].pack[packNum].packInfo[voltage][0] = readWordData[0];
          module[_M2].pack[packNum].packInfo[voltage][1] = readWordData[1];
        }
      }
    }//if(status & BIT1){
    if(status & BIT2){
      //module3 pack
        flag = setPackMosFET(_M3, DeviceOff);
        if(flag){
          flag = setPackMosFET(_M3, DeviceOff);
        }
      if(flag){
        Init_USCI_B2_IIC();
        module[_M3].pack[packNum].packFail = PackCommunctionFail;
        DeltaValue++;
      }else{
        // update voltage and ManufacturerAccess
        module[_M3].pack[packNum].packInfo[ManufacturerAccess][0] = 0x00;
        module[_M3].pack[packNum].packInfo[ManufacturerAccess][1] = 0x00;
        cmd = PackCommand[voltage];
        readWordData[0] = 0;
        readWordData[1] = 0;
        gettingStatus = getPackInformation(_M3, cmd, readWordData);
        if(gettingStatus == None){
          module[_M3].pack[packNum].packInfo[voltage][0] = readWordData[0];
          module[_M3].pack[packNum].packInfo[voltage][1] = readWordData[1];
        }
      }
    }//if(status & BIT2){
    if(DeltaValue){
      //return;
    }
  }//if(status != 0){

  
  /////////////////////////////////////////////
  // if the pack change new one
  //check voltage, if pack has to be turned off
  if(status != 0){
    if(status & BIT0){
      //module1 pack
      DeltaValue = getDeltaVoltageWithMosFETOn(_M1, packNum);
      if(DeltaValue > PackConnectOnDeltaVoltageTH){
        //turn off
        flag = setPackMosFET(_M1, DeviceOff);
      }else{
        //turn on
        flag = setPackMosFET(_M1, DeviceOn);
        __delay_cycles(5000);
        flag |= setPackMosFET(_M1, DeviceOn);
      }
      if(flag){
        Init_USCI_B0_IIC();
        module[_M1].pack[packNum].packFail = PackCommunctionFail;
      }
    }//if(status & BIT0){
    if(status & BIT1){
      //module2 pack
      DeltaValue = getDeltaVoltageWithMosFETOn(_M2, packNum);
      if(DeltaValue > PackConnectOnDeltaVoltageTH){
        //turn off
        flag = setPackMosFET(_M2, DeviceOff);
      }else{
        //turn on
        flag = setPackMosFET(_M2, DeviceOn);
        __delay_cycles(5000);
        flag |= setPackMosFET(_M2, DeviceOn);
      }
      if(flag){
        Init_USCI_B1_IIC();
        module[_M2].pack[packNum].packFail = PackCommunctionFail;
      }    
    }//if(status & BIT1){
    if(status & BIT2){
      //module3 pack
      DeltaValue = getDeltaVoltageWithMosFETOn(_M3, packNum);
      if(DeltaValue > PackConnectOnDeltaVoltageTH){
        //turn off
        flag = setPackMosFET(_M3, DeviceOff);
      }else{
        //turn on
        flag = setPackMosFET(_M3, DeviceOn);
        __delay_cycles(5000);
        flag |= setPackMosFET(_M3, DeviceOn);
      }
      if(flag){
        Init_USCI_B2_IIC();
        module[_M3].pack[packNum].packFail = PackCommunctionFail;
      }    
    }//if(status & BIT2){
  }//if(status != 0){
  
  
  //
  status = CheckingPackVoltageForMosFETConnectingInto( packNum );
  /////////////////////////////////////////////////////////////
  //Update MosFET Status
  if(status != 0){
    if(status & BIT0){
      //module1 pack
      cmd = _FETControl_;
      readWordData[0] = 0;
      readWordData[1] = 0;
      gettingStatus = getPackInformation(_M1, cmd, readWordData);
      if(gettingStatus == None && readWordData[1] == 0){
        module[_M1].pack[packNum].packInfo[ManufacturerAccess][0] = readWordData[0];
        module[_M1].pack[packNum].packInfo[ManufacturerAccess][1] = readWordData[1];
      }
    }//if(status & BIT0){
    if(status & BIT1){
      //module2 pack
      cmd = _FETControl_;
      readWordData[0] = 0;
      readWordData[1] = 0;
      gettingStatus = getPackInformation(_M2, cmd, readWordData);
      if(gettingStatus == None && readWordData[1] == 0){
        module[_M2].pack[packNum].packInfo[ManufacturerAccess][0] = readWordData[0];
        module[_M2].pack[packNum].packInfo[ManufacturerAccess][1] = readWordData[1];
      }
    }//if(status & BIT1){
    if(status & BIT2){
      //module3 pack
      cmd = _FETControl_;
      readWordData[0] = 0;
      readWordData[1] = 0;
      gettingStatus = getPackInformation(_M3, cmd, readWordData);
      if(gettingStatus == None && readWordData[1] == 0){
        module[_M3].pack[packNum].packInfo[ManufacturerAccess][0] = readWordData[0];
        module[_M3].pack[packNum].packInfo[ManufacturerAccess][1] = readWordData[1];
      }
    }//if(status & BIT2){
  }//if(status != 0){  
  
  //CheckingPackMosFETStatus( packNum );

 
}//void PackMosFETControlAtchangingNewOne( char packNum, unsigned char *Out_packChangedNewOneBit ){

 unsigned char CheckingPackVoltageForMosFETConnectingInto( char packNum ){

  char flag;
  unsigned char status;
  unsigned int DeltaValue;

  status = 0;
  // check mosfet, if it turn off
  //M1
  if(module[_M1].pack[packNum].packFail == PackNormal){
    if(!isPackFETTurnOn_ByManufacturerAccess(_M1, packNum)){
      DeltaValue = getDeltaVoltageWithMosFETOn(_M1, packNum);
      if(DeltaValue <= PackConnectOnDeltaVoltageTH){
        //turn on
        flag = setPackMosFET(_M1, DeviceOn);
        __delay_cycles(5000);
        flag |= setPackMosFET(_M1, DeviceOn);
        status |= BIT0;
        if(flag){
          Init_USCI_B0_IIC();
        }    
      }
    }
  }
  
  //M2
  if(module[_M2].pack[packNum].packFail == PackNormal){
    if(!isPackFETTurnOn_ByManufacturerAccess(_M2, packNum)){
      DeltaValue = getDeltaVoltageWithMosFETOn(_M2, packNum);
      if(DeltaValue <= PackConnectOnDeltaVoltageTH){
        //turn on
        flag = setPackMosFET(_M2, DeviceOn);
        __delay_cycles(5000);
        flag |= setPackMosFET(_M2, DeviceOn);
        status |= BIT1;
        if(flag){
          Init_USCI_B1_IIC();
        }    
      }
    }
  }
  //M3
  if(module[_M3].pack[packNum].packFail == PackNormal){
    if(!isPackFETTurnOn_ByManufacturerAccess(_M3, packNum)){
      DeltaValue = getDeltaVoltageWithMosFETOn(_M3, packNum);
      if(DeltaValue <= PackConnectOnDeltaVoltageTH){
        //turn on
        flag = setPackMosFET(_M3, DeviceOn);
        __delay_cycles(5000);
        flag |= setPackMosFET(_M3, DeviceOn);
        status |= BIT2;
        if(flag){
          Init_USCI_B2_IIC();
        }    
      }
    }
  }
  
  return status;
}//void CheckingPackVoltageForMosFETConnectingInto( char packNum ){


void CheckingPackMosFETAbnormalStatus( char packNum ){
  unsigned int DeltaValue;
  unsigned char flag;
  /////////////////////////////////////////////////////////////////
  // check mos fet if it is not all close or all open  
  //_M1
  if(module[_M1].pack[packNum].packFail == PackNormal){
    DeltaValue = 0;
    if(module[_M1].pack[packNum].packInfo[ManufacturerAccess][0] & PackFETDSGBit){
      DeltaValue++;
    }
    if(module[_M1].pack[packNum].packInfo[ManufacturerAccess][0] & PackFETCHGBit){
      DeltaValue++;
    }
    if(DeltaValue == 0 || DeltaValue == 2){
      //Pack Mos FET are control Normal
    }else{
      //Pack Mos FETs show one mosfet is turned on and other one is turned off, abnormal.
      flag = setPackMosFET(_M1, DeviceOff);
      if(flag){
        Init_USCI_B0_IIC();
        module[_M1].pack[packNum].packFail = PackCommunctionFail;
      }    
    }
  }
  
  //_M2
  if(module[_M2].pack[packNum].packFail == PackNormal){
    DeltaValue = 0;
    if(module[_M2].pack[packNum].packInfo[ManufacturerAccess][0] & PackFETDSGBit){
      DeltaValue++;
    }
    if(module[_M2].pack[packNum].packInfo[ManufacturerAccess][0] & PackFETCHGBit){
      DeltaValue++;
    }
    if(DeltaValue == 0 || DeltaValue == 2){
      //Pack Mos FET are control Normal
    }else{
      //Pack Mos FETs show one mosfet is turned on and other one is turned off, abnormal.
      flag = setPackMosFET(_M2, DeviceOff);
      if(flag){
        Init_USCI_B1_IIC();
        module[_M2].pack[packNum].packFail = PackCommunctionFail;
      }    
    }
  }
  //_M3
  if(module[_M3].pack[packNum].packFail == PackNormal){
    DeltaValue = 0;
    if(module[_M3].pack[packNum].packInfo[ManufacturerAccess][0] & PackFETDSGBit){
      DeltaValue++;
    }
    if(module[_M3].pack[packNum].packInfo[ManufacturerAccess][0] & PackFETCHGBit){
      DeltaValue++;
    }
    if(DeltaValue == 0 || DeltaValue == 2){
      //Pack Mos FET are control Normal
    }else{
      //Pack Mos FETs show one mosfet is turned on and other one is turned off, abnormal.
      flag = setPackMosFET(_M3, DeviceOff);
      if(flag){
        Init_USCI_B2_IIC();
        module[_M3].pack[packNum].packFail = PackCommunctionFail;
      }    
    }      
  }

}//void CheckingPackMosFETStatus(){



char setPackMosFET(char moduleName, char enable){
  
  unsigned char cmd;
  unsigned char writeWordData[2];
  char packFailFlag;
  unsigned char retry = 0;
  
    if(enable){
      writeWordData[0] = 0x06;
    }else{
      writeWordData[0] = 0x00;
    }
    writeWordData[1] = 0x00;
    
  do //for retry
  {
    packFailFlag = None;
    switch(moduleName){
      case _M1:
        packFailFlag = SMBUS0_WriteWord_PEC(_FETControl_, writeWordData);
        break;
      case _M2:
        packFailFlag = SMBUS1_WriteWord_PEC(_FETControl_, writeWordData);
        break;
      case _M3:
        packFailFlag = SMBUS2_WriteWord_PEC(_FETControl_, writeWordData);
        break;
      default:
        return PackAbnormalStatus;// out of this function
      }
      if(packFailFlag == None ){
        break;
      }else{
        for(cmd = 0; cmd < 10; cmd++){
          __delay_cycles(5000);
        }
      }
    }while(++retry < Retry_Attempts);

  __delay_cycles(5000);
  return packFailFlag;
}
char isPackFETTurnOn_ByManufacturerAccess(char moduleName, char packNum){
    if((module[moduleName].pack[packNum].packInfo[ManufacturerAccess][0] & PackFETDSGBit) &&
      (module[moduleName].pack[packNum].packInfo[ManufacturerAccess][0] & PackFETCHGBit))
   {
     // mos fet turn on
     return true;
   }else{
     return false;
   }
}







